package com.aca.market.controller;


import com.aca.market.entity.Role;
import com.aca.market.entity.User;
import com.aca.market.service.IPermissionService;
import com.aca.market.service.IRolePermService;
import com.aca.market.service.IRoleService;
import com.aca.market.service.IUserService;
import com.aca.market.util.MD5;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.crypto.hash.SimpleHash;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.util.ByteSource;
import org.apache.shiro.web.util.WebUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import java.time.LocalDateTime;
import java.util.List;

/**
 * <p>
 * 用户表 前端控制器
 * </p>
 *
 * @author aca
 * @since 2020-11-13
 */
@Slf4j
@Controller
public class UserController {

    @Autowired
    IUserService userService;
    @Autowired
    IRolePermService rolePermService;
    @Autowired
    IPermissionService permissionService;
    @Autowired
    IRoleService roleService;

    @GetMapping("/login")
    public String toLogin(){
        if (userService.nowUser() != null) return "redirect:/dashboard";
        return "login";
    }

    @GetMapping("/register")
    public String toRegister(){
        if (userService.nowUser() != null) return "redirect:/dashboard";
        return "register";
    }

    @GetMapping({"/","/index"})
    public String toIndex(){
        return "index";
    }

    @PostMapping("/register")
    @ResponseBody
    public Boolean userRegister(User user){
        user.setPassword(MD5.getCode(user.getUsername(), user.getPassword(), 1))
                .setRoleId(17L)
                .setGender(0)
                .setCreatedTime(LocalDateTime.now())
                .setUpdatedTime(LocalDateTime.now());
        boolean flag = userService.save(user);
        SecurityUtils.getSubject().getSession().setAttribute("msg","注册成功！");
        return flag;
    }

    @ResponseBody
    @RequestMapping(value = "/verifyUserName",method = RequestMethod.GET)
    public boolean verifyUserName(@RequestParam("username")String name){
        List<User> users = userService.list(new QueryWrapper<User>().eq("username",name));
        log.info("=============verifyUserName:{}==>len:" + users,name);
        return users.isEmpty();
    }

    @ResponseBody
    @RequestMapping(value = "/verifyUserPhone",method = RequestMethod.GET)
    public boolean verifyUserPhone(@RequestParam("phone")String phone){
        List<User> users = userService.list(new QueryWrapper<User>().eq("phone",phone));
        log.info("=============verifyUserPhone:{}==>len:" + users,phone);
        return users.isEmpty();
    }

    @ResponseBody
    @RequestMapping(value = "/verifyUserEmail",method = RequestMethod.GET)
    public boolean verifyUserEmail(@RequestParam("email")String email){
        List<User> users = userService.list(new QueryWrapper<User>().eq("email",email));
        log.info("=============verifyUserPhone:{}==>len:" + users,email);
        return users.isEmpty();
    }

    @PostMapping("/login")
    public String login(String username, String password, Boolean rememberMe,
                        ServletRequest request, ServletResponse response){
        System.out.println("================1.getSubject()");
        //获取当前用户
        Subject subject = SecurityUtils.getSubject();
        Session session = subject.getSession();
        //*************要先加密再建token **************
        ByteSource salt = ByteSource.Util.bytes(username);
        //hashlterations 混淆次数
        SimpleHash hash = new SimpleHash("MD5",password,salt,1);
        String pwd = hash.toString();

        UsernamePasswordToken token = new UsernamePasswordToken(username,pwd);
        if (rememberMe != null) {
            token.setRememberMe(rememberMe);
        }
        try {
            //执行登陆 无异常就ok
            System.out.println("===============2.subject.login");
            subject.login(token);

            // 获取当前user
            User user = (User) subject.getPrincipal();
            session.setAttribute("user",user);
//            session.setAttribute(session.getId(),user.getId());
            //返回登陆前页面
            //shiro把session和request都封装了
//            session.getAttribute("shiroSavedRequest");
//            SavedRequest savedRequest = (SavedRequest)SecurityUtils.getSubject().getSession().getAttribute("shiroSavedRequest");
            //前提是有登陆前页面，不然空指针
            //不跳转问题：filterMap的配置没配好 不是anon才会记录原url
            if (WebUtils.getSavedRequest(request) != null){
                String url = WebUtils.getSavedRequest(request).getRequestUrl();
                System.out.println("==================URL" +url);
                return "redirect:" + url;
            }
            return "redirect:/dashboard";
//            WebUtils.redirectToSavedRequest(request,response,url);
//            SavedRequest savedRequest = WebUtils.getSavedRequest(request);
            // 取得url之后对SavedRequest进行清空
//            WebUtils.getAndClearSavedRequest(savedRequest);
        } catch (AuthenticationException e) {
            session.setAttribute("err","登录失败");
            System.out.println(e.getMessage());
            return "login";
        }
    }

    @GetMapping("/logout")
    public String logout(){
        SecurityUtils.getSubject().logout();
        return "login";
    }



//    @RequiresRoles("")
    @GetMapping("/user/list")
    public String listUser(Model model){
        List<User> users = userService.list();
        //还有权限 (userId:perm)
//        List<Permission> perms = permissionService.getPermsEntity(user.getRoleId());
//        model.addAttribute("perms",perms);
        model.addAttribute("users",users);
        return "user-list";
    }

    @GetMapping("/user/detail")
    public String getUser(@RequestParam(value = "userId") Long userId, Model model){
        User user = userService.getById(userId);
        model.addAttribute("userDetail",user);
        return "user-detail";
    }

//    @GetMapping("/user/detail/")
//    @ResponseBody
//    public User getUser(@RequestParam(value = "userId") Long userId, Model model){
//        User user = userService.getById(userId);
//        model.addAttribute("userDetail"+userId.toString(),user);
//        return user;
//    }

    @GetMapping("/user/del")
    public String delUser(@RequestParam("userId") Long userId){
        userService.removeById(userId);
        return "redirect:/user/list";
    }

    //删多个
    // 不建议使用DELETE，原因在于：根据RFC标准文档，DELETE请求的body在语义上没有任何意义。
    // 事实上一些网关、代理、防火墙在收到DELETE请求后，会把请求的body直接剥离掉。
    @PostMapping("/user/delete/{userIdList}")
    public String delUsers(@PathVariable("userIdList") List<Long> userIdList){
        userService.removeByIds(userIdList);
        return "redirect:/user/list";
    }


    @PostMapping("/user/update")
    public String updateUser(User user){
        User tmp = user;
        System.out.println(tmp);
        String originPwd = userService.getById(user.getId()).getPassword();
        if (tmp.getUsername()!=null && tmp.getPassword()!=null){
            tmp.setUpdatedTime(LocalDateTime.now());
            //和原密码不同才改
            if (originPwd != user.getPassword()){
                String pwd = MD5.getCode(tmp.getUsername(), tmp.getPassword(), 1);
                System.out.println("update... MD5->>>>>>"+pwd);
                tmp.setPassword(pwd);
            }
            userService.updateById(tmp);
            System.out.println("============updateUser ok: " + tmp.toString());
//            return tmp;
            return "redirect:/user/list";
        }
        System.out.println("============updateUser fail");
        return "fail";
//        return tmp;
    }

    @PostMapping("/user/add")
    public String addUser(User user){
        User tmp = user;
        //不能加入重复的邮箱或者电话号 会报重复索引错误
        // SQLIntegrityConstraintViolationException:Duplicate entry '' for key''
        LocalDateTime now = LocalDateTime.now();
        String pwd = MD5.getCode(tmp.getUsername(), tmp.getPassword(), 1);
        tmp.setUpdatedTime(now).setCreatedTime(now);
        tmp.setPassword(pwd);
        userService.save(tmp);
        return "redirect:/user/list";
    }

    @GetMapping("/user/toAdd")
    public String toAddUser(Model model){
        List<Role> roles = roleService.list(new QueryWrapper<Role>().notIn("id", 1L));
        model.addAttribute("roles",roles);
        return "user-add";
    }




}

